<template>
  <div class="canvas-area">
    <!-- 可视化编排区域 -->
    <div ref="canvas" class="canvas"></div>

    <!-- 操作按钮 -->
    <div class="toolbar">
      <el-button type="primary" @click="autoConnect">自动连线</el-button>
      <el-button type="success" @click="ruleMonitor">规则监测</el-button>
      <el-button type="warning" @click="refreshOperators">刷新算子</el-button>

      <!-- 导出按钮使用 el-dropdown -->
      <el-dropdown @command="handleExportCommand">
        <el-button type="primary" style="margin-inline: 10px;">
          导出<i class="el-icon-arrow-down el-icon--right"></i>
        </el-button>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="png">导出 PNG</el-dropdown-item>
          <el-dropdown-item command="svg">导出 SVG</el-dropdown-item>
          <el-dropdown-item command="json">导出 JSON</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <el-button type="danger" @click="clearCanvas">清空画布</el-button>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex';
import { jsPlumb } from 'jsplumb'; // 引入 jsPlumb 库用于绘制连线
import html2canvas from 'html2canvas'; // 用于导出 PNG

export default {
  name: 'CanvasArea',
  data() {
    return {
      jsPlumbInstance: null,
      draggedOperator: null,
    };
  },
  computed: {
    ...mapState('operators', ['operators'])
  },
  mounted() {
    this.initializeJsPlumb();
    this.$EventBus.$on('operator-dragged', this.addOperatorToCanvas);
  },
  beforeDestroy() {
    this.$EventBus.$off('operator-dragged', this.addOperatorToCanvas);
  },
  methods: {
    initializeJsPlumb() {
      this.jsPlumbInstance = jsPlumb.getInstance({
        Connector: ["Flowchart", { curviness: 10 }],
        PaintStyle: { stroke: "#567567", strokeWidth: 2 },
        EndpointStyle: { radius: 5, fill: "#567567" },
        Anchors: ["TopCenter", "BottomCenter"],
        Container: this.$refs.canvas, // 确保容器是画布的引用
        DragOptions: { cursor: 'pointer', zIndex: 2000 }
      });

      console.log('jsPlumb initialized with container:', this.$refs.canvas);
    },
    addOperatorToCanvas(operator) {
      console.log('Received operator:', operator); // 打印接收到的算子数据

      const operatorElement = document.createElement('div');
      operatorElement.className = 'operator-item';
      operatorElement.id = `operator-${operator.id}`;
      operatorElement.innerHTML = `<span>${operator.name}</span>`;

      // 设置随机位置
      const randomLeft = Math.random() * 80 + 10;
      const randomTop = Math.random() * 80 + 10;
      operatorElement.style.position = 'absolute';
      operatorElement.style.left = `${randomLeft}%`;
      operatorElement.style.top = `${randomTop}%`;

      // 将算子元素插入到画布中
      this.$refs.canvas.appendChild(operatorElement);
      console.log('Operator element added to canvas:', operatorElement);

      // 添加端点
      try {
        this.jsPlumbInstance.addEndpoint(operatorElement, { anchor: "TopCenter" }, this.getEndpointOptions());
        this.jsPlumbInstance.addEndpoint(operatorElement, { anchor: "BottomCenter" }, this.getEndpointOptions());
        console.log('Endpoints added to operator:', operatorElement.id);
      } catch (error) {
        console.error('Error adding endpoints:', error);
      }

      // 使操作符可以拖动
      try {
        this.makeDraggable(operatorElement);
        console.log('Operator made draggable:', operatorElement.id);
      } catch (error) {
        console.error('Error making operator draggable:', error);
      }
    },
    getEndpointOptions() {
      return {
        isSource: true,
        isTarget: true,
        maxConnections: -1,
        endpoint: ["Dot", { radius: 5 }],
        paintStyle: { fill: "#567567" },
        hoverPaintStyle: { fill: "red" }
      };
    },
    makeDraggable(element) {
      this.jsPlumbInstance.draggable(element, {
        containment: this.$refs.canvas,
        grid: [20, 20],
        stop: () => {
          console.log('Operator moved:', element.id);
        }
      });
    },
    autoConnect() {
      // 自动连线逻辑
      const operators = Array.from(this.$refs.canvas.getElementsByClassName('operator-item'));
      operators.forEach((op1, index) => {
        if (index < operators.length - 1) {
          this.jsPlumbInstance.connect({ source: op1.id, target: operators[index + 1].id });
        }
      });
      console.log('Auto connect executed');
    },
    // 规则监测逻辑
    ruleMonitor() {
      console.log('Rule monitor executed');

      // 获取所有的连接
      const connections = this.jsPlumbInstance.getAllConnections();

      // 过滤出没有标签的连接
      const invalidConnections = connections.filter(conn => !conn.getLabel());

      if (invalidConnections.length > 0) {
        // 所有连接都已标记
        this.$message.success('所有连接均已标记');
      } else {
        // 如果存在未标记的连接，弹出警告信息
        this.$message.warning('存在未标记的连接！');
      }
    },
    refreshOperators() {
      // 刷新算子逻辑
      this.$store.dispatch('operators/fetchOperators').then(() => {
        console.log('Operators refreshed');
        this.$message.success('算子已刷新');
      });
    },
    handleExportCommand(command) {
      this.exportDiagram(command);
    },
    exportDiagram(format) {
      switch (format) {
        case 'png':
          html2canvas(this.$refs.canvas).then(canvas => {
            const link = document.createElement('a');
            link.href = canvas.toDataURL('image/png');
            link.download = 'diagram.png';
            link.click();
            console.log('Diagram exported as PNG');
          });
          break;
        case 'svg':
          const svgString = this.generateSvg();
          const blob = new Blob([svgString], { type: 'image/svg+xml' });
          const url = URL.createObjectURL(blob);
          const link = document.createElement('a');
          link.href = url;
          link.download = 'diagram.svg';
          link.click();
          console.log('Diagram exported as SVG');
          break;
        case 'json':
          const diagramData = this.generateJson();
          const jsonBlob = new Blob([JSON.stringify(diagramData, null, 2)], { type: 'application/json' });
          const jsonUrl = URL.createObjectURL(jsonBlob);
          const jsonLink = document.createElement('a');
          jsonLink.href = jsonUrl;
          jsonLink.download = 'diagram.json';
          jsonLink.click();
          console.log('Diagram exported as JSON');
          break;
      }
    },
    generateSvg() {
      const canvas = this.$refs.canvas;
      const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      svg.setAttribute('width', canvas.offsetWidth);
      svg.setAttribute('height', canvas.offsetHeight);

      Array.from(canvas.children).forEach(child => {
        const rect = child.getBoundingClientRect();
        const foreignObject = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
        foreignObject.setAttribute('x', rect.x);
        foreignObject.setAttribute('y', rect.y);
        foreignObject.setAttribute('width', rect.width);
        foreignObject.setAttribute('height', rect.height);
        foreignObject.appendChild(child.cloneNode(true));
        svg.appendChild(foreignObject);
      });

      return new XMLSerializer().serializeToString(svg);
    },
    generateJson() {
      const connections = this.jsPlumbInstance.getAllConnections();
      const operators = Array.from(this.$refs.canvas.getElementsByClassName('operator-item')).map(op => ({
        id: op.id,
        name: op.querySelector('span').innerText,
        x: op.offsetLeft,
        y: op.offsetTop
      }));

      return {
        operators,
        connections: connections.map(conn => ({
          source: conn.sourceId,
          target: conn.targetId
        }))
      };
    },
    clearCanvas() {
      // 清除所有算子和连接
      const canvas = this.$refs.canvas;
      while (canvas.firstChild) {
        canvas.removeChild(canvas.firstChild);
      }

      // 清除所有 jsPlumb 连接
      this.jsPlumbInstance.reset();

      console.log('Canvas cleared');
    }
  }
};
</script>

<style scoped>
.canvas-area {
  position: relative;
  width: 100%;
  height: calc(100vh - 60px); /* 减去顶部工具栏的高度 */
  background-color: #f9f9f9;
}

.canvas {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
}

.toolbar {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1000;
}

.operator-item {
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: #fff;
  cursor: move;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
</style>
